package com.coursehub.coursemanagement.service;

import com.coursehub.course.entity.Course;
import com.coursehub.course.entity.CourseStudent;
import com.coursehub.course.entity.CourseStudentId;
import com.coursehub.course.repository.CourseRepository;
import com.coursehub.course.repository.CourseStudentRepository;
// import com.coursehub.learningprogress.entity.Progress; // 跨服务实体，通过API调用
import com.coursehub.shared.client.ServiceClient;
import com.coursehub.shared.transaction.AbstractTransactionStep;
import com.coursehub.shared.transaction.DistributedTransactional;
import com.coursehub.shared.transaction.DistributedTransactionManager;
import com.coursehub.shared.transaction.TransactionResult;
import com.coursehub.course.transaction.InitializeQuestionBanksStep;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import jakarta.servlet.http.HttpServletRequest;

/**
 * 学生选课分布式事务服务
 * 协调课程管理服务和学习进度服务的操作
 */
@Slf4j
@Service
public class EnrollmentTransactionService {
    
    @Autowired
    private DistributedTransactionManager transactionManager;
    
    @Autowired
    private CourseRepository courseRepository;
    
    @Autowired
    private CourseStudentRepository courseStudentRepository;
    
    @Autowired
    private ServiceClient serviceClient;
    
    @Autowired
    private InitializeQuestionBanksStep initializeQuestionBanksStep;
    
    /**
     * 学生选课分布式事务
     * 需要同时更新课程选课人数和创建学习进度记录
     */
    @DistributedTransactional(value = "学生选课", description = "学生选课分布式事务")
    public CompletableFuture<TransactionResult> enrollStudent(String studentId, String courseId) {
        // 获取当前请求的头信息
        String authorizationHeader = null;
        String userIdHeader = null;
        String userAccountHeader = null;
        try {
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            if (attributes != null) {
                HttpServletRequest request = attributes.getRequest();
                authorizationHeader = request.getHeader("Authorization");
                userIdHeader = request.getHeader("X-User-Id");
                userAccountHeader = request.getHeader("X-User-Account");
                log.info("获取到头信息: Authorization={}, X-User-Id={}, X-User-Account={}", 
                        authorizationHeader != null ? "Bearer ***" : "null",
                        userIdHeader, userAccountHeader);
            }
        } catch (Exception e) {
            log.warn("获取请求头失败: {}", e.getMessage());
        }
        
        String transactionId = transactionManager.beginTransaction("学生选课-" + studentId + "-" + courseId);
        
        try {
            // 步骤1: 检查课程是否存在并添加学生到课程
            transactionManager.addStep(transactionId, new UpdateCourseEnrollmentStep(courseId, studentId));
            
            // 步骤2: 创建学习进度记录
            transactionManager.addStep(transactionId, new CreateProgressStep(studentId, courseId, authorizationHeader, userIdHeader, userAccountHeader));
            
            // 步骤3: 初始化收藏题库和错题库
            initializeQuestionBanksStep.setParameters(studentId, courseId, authorizationHeader, userIdHeader, userAccountHeader);
            transactionManager.addStep(transactionId, initializeQuestionBanksStep);
            
            // 执行分布式事务
            return transactionManager.executeTransaction(transactionId);
            
        } catch (Exception e) {
            log.error("学生选课事务准备失败: 学生ID={}, 课程ID={}, 错误: {}", studentId, courseId, e.getMessage(), e);
            transactionManager.cancelTransaction(transactionId);
            return CompletableFuture.completedFuture(
                TransactionResult.failure("学生选课事务准备失败: " + e.getMessage(), e)
            );
        }
    }
    
    /**
     * 更新课程选课人数事务步骤
     */
    private class UpdateCourseEnrollmentStep extends AbstractTransactionStep {
        private final String courseId;
        private final String studentId;
        private Course originalCourse;
        private boolean studentAdded = false;
        
        public UpdateCourseEnrollmentStep(String courseId, String studentId) {
            super("更新课程选课人数", "添加学生到课程并增加选课人数");
            this.courseId = courseId;
            this.studentId = studentId;
        }
        
        @Override
        protected void doExecute() throws Exception {
            // 查找课程
            originalCourse = courseRepository.findById(courseId)
                .orElseThrow(() -> new Exception("课程不存在: " + courseId));
            
            // 检查学生是否已经选修了该课程
            if (courseStudentRepository.existsByCourseIdAndUserId(courseId, studentId)) {
                throw new Exception("学生已选修该课程: studentId=" + studentId + ", courseId=" + courseId);
            }
            
            // 添加学生到课程
            CourseStudentId courseStudentId = new CourseStudentId(courseId, studentId);
            CourseStudent courseStudent = new CourseStudent(courseStudentId, originalCourse);
            courseStudentRepository.save(courseStudent);
            studentAdded = true;
            
            // 获取当前选课学生数量
            int currentStudentCount = courseStudentRepository.findByCourse_CourseId(courseId).size();
            
            log.info("成功添加学生到课程: studentId={}, courseId={}, 当前学生数量={}", 
                    studentId, courseId, currentStudentCount);
        }
        
        @Override
        protected void doCompensate() throws Exception {
            if (studentAdded) {
                try {
                    // 删除已添加的学生记录
                    CourseStudentId courseStudentId = new CourseStudentId(courseId, studentId);
                    courseStudentRepository.deleteById(courseStudentId);
                    
                    log.info("成功补偿删除学生选课记录: studentId={}, courseId={}", studentId, courseId);
                } catch (Exception e) {
                    log.error("补偿删除学生选课记录失败: studentId={}, courseId={}, 错误: {}", 
                             studentId, courseId, e.getMessage(), e);
                    throw new Exception("补偿删除学生选课记录失败: " + e.getMessage(), e);
                }
            }
        }
        
        @Override
        public boolean canExecute() {
            return courseId != null && !courseId.trim().isEmpty() &&
                   studentId != null && !studentId.trim().isEmpty();
        }
    }
    
    /**
     * 创建学习进度记录事务步骤
     */
    private class CreateProgressStep extends AbstractTransactionStep {
        private final String studentId;
        private final String courseId;
        private final String authorizationHeader;
        private final String userIdHeader;
        private final String userAccountHeader;
        private String createdProgressId;
        
        public CreateProgressStep(String studentId, String courseId, String authorizationHeader, String userIdHeader, String userAccountHeader) {
            super("创建学习进度记录", "在学习进度服务中创建学习进度记录");
            this.studentId = studentId;
            this.courseId = courseId;
            this.authorizationHeader = authorizationHeader;
            this.userIdHeader = userIdHeader;
            this.userAccountHeader = userAccountHeader;
        }
        
        @Override
        protected void doExecute() throws Exception {
            try {
                // 构建学习进度数据
                Map<String, Object> progressData = new HashMap<>();
                progressData.put("studentId", studentId);
                progressData.put("courseId", courseId);
                progressData.put("completionPercentage", 0.0);
                progressData.put("startTime", LocalDateTime.now());
                progressData.put("lastAccessTime", LocalDateTime.now());
                
                // 调用学习进度服务创建记录
                String response;
                if (authorizationHeader != null) {
                    // 设置所有头信息
                    Map<String, String> headers = new HashMap<>();
                    headers.put("Authorization", authorizationHeader);
                    if (userIdHeader != null) {
                        headers.put("X-User-Id", userIdHeader);
                    }
                    if (userAccountHeader != null) {
                        headers.put("X-User-Account", userAccountHeader);
                    }
                    response = serviceClient.post(
                        "learning-progress",
                        "/api/progress", 
                        progressData, 
                        String.class,
                        headers
                    );
                    log.info("使用完整头信息调用learning-progress服务: Authorization={}, X-User-Id={}, X-User-Account={}", 
                            "Bearer ***", userIdHeader, userAccountHeader);
                } else {
                    response = serviceClient.post(
                        "learning-progress",
                        "/api/progress", 
                        progressData, 
                        String.class
                    );
                    log.warn("未找到Authorization头，直接调用learning-progress服务");
                }
                
                // 假设返回的是创建的进度记录ID
                createdProgressId = response;
                
                log.info("成功创建学习进度记录: 学生ID={}, 课程ID={}, 进度ID={}", 
                        studentId, courseId, createdProgressId);
                
            } catch (Exception e) {
                log.error("创建学习进度记录失败: 学生ID={}, 课程ID={}, 错误: {}", 
                         studentId, courseId, e.getMessage(), e);
                throw new Exception("创建学习进度记录失败: " + e.getMessage(), e);
            }
        }
        
        @Override
        protected void doCompensate() throws Exception {
            if (createdProgressId != null) {
                try {
                    // 调用学习进度服务删除记录
                    serviceClient.delete(
                        "learning-progress",
                        "/api/progress/" + createdProgressId,
                        String.class
                    );
                    
                    log.info("成功补偿删除学习进度记录: 进度ID={}", createdProgressId);
                    
                } catch (Exception e) {
                    log.error("补偿删除学习进度记录失败: 进度ID={}, 错误: {}", 
                             createdProgressId, e.getMessage(), e);
                    throw new Exception("补偿删除学习进度记录失败: " + e.getMessage(), e);
                }
            }
        }
        
        @Override
        public boolean canExecute() {
            return studentId != null && !studentId.trim().isEmpty() && 
                   courseId != null && !courseId.trim().isEmpty();
        }
    }
}